/* 
 * File:   JAdapter.cpp
 * Author: johnneyshi
 * 
 * Created on 2013年3月4日, 上午9:43
 */

#include "JAdapter.h"
#include "JServerMaster.h"
#include "JDefine.h"
#include <string.h>

extern pthread_mutex_t needDealFdsLock;
pthread_mutex_t toWorkerFdsLock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t bufferVectorLock = PTHREAD_MUTEX_INITIALIZER;

JAdapter::JAdapter() {
}

/*
 * 这里还需要一种机制：如果客户端拒绝攻击，或者发送的数据没有到size大小，那么就循环，从队列中另外再取一个描述符，进行处理
 * 但是原来的描述符，也用epoll监听着，最后只有接受到size大小的数据，才发往worker
 */
void JAdapter::Start(AdapterThreadArg* pArg)
{
    pthread_mutex_lock(&bufferVectorLock);
    JBuffer* pBuff = pArg->pMaster->GetAvailableBuffer();///////////////////////////////需要上锁
    pthread_mutex_unlock(&bufferVectorLock);
    char buff[BUFF_SIZE];
    int needReadCount = 0,n = 0;
    int toMasterConnFd = -1;
    int toWorkerConnFd = -1,toWorkerConnFdIndex = -1;
    //设置这个是为了，如果客户端和服务器建立连接，如果要传输多次信息，但是不断开连接
    bool isCycleEnd = true;
    while(true)
    {
        if(isCycleEnd == true)
        {
            //从needDealFds中取fd
            toMasterConnFd = -1;
            while(true)
            {
                pthread_mutex_lock(&needDealFdsLock);
                if(!pArg->pMaster->needDealFds.empty())//////////////////////////////这里需要优化，不能
                {
                    toMasterConnFd = pArg->pMaster->needDealFds.front();//从共享文件中得到数据
                    pArg->pMaster->needDealFds.pop();
                }
                pthread_mutex_unlock(&needDealFdsLock);
                if(toMasterConnFd == -1)
                {
                    usleep(10);
                }
                else
                {
                    break;
                }
            }
        }
        //缓存数据
        //首先先把toMasterConnFd存入数据中，因为在返回数据的时候，还要用到toMasterConnFd,
        //问题：如果返回时，toMasterConnFd已经连接中断……////////////////////////////////////////////////////
        //pBuff->Put((char*)&toMasterConnFd,SIZEOF_INT);
        //读取数据块的大小
        unsigned int size = 0;
        n = read(toMasterConnFd,(void*)&size,SIZEOF_UNSIGNED_INT);////////////////////////为了防止拒绝攻击，这里需设置nonblock
        //if(n < 0 && errno == EINTR)/////////////////////////////////////////////////////
        //当客户端向服务器写一个size=0的数据时，代表连接结束
        if(size == 0)
        {
            isCycleEnd = true;
            close(toMasterConnFd);
            continue;
        }
        pBuff->Put((char*)&size,SIZEOF_UNSIGNED_INT);
        bzero(buff,BUFF_SIZE);
        while(size > 0)
        {
            if(size > BUFF_SIZE)
            {
                needReadCount = BUFF_SIZE;
            }
            else
            {
                needReadCount = size;
            }
            n = read(toMasterConnFd,buff,needReadCount);
            size -= n;
            pBuff->Put(buff,n);
            //这里不许要用下面语句，因为是根据n来写道pBuff中的
            //bzero(buff,BUFF_SIZE);
        }
        /*接受完数据,选取toWorkerFd，这里必须要找到toWorkerFd,如果没有，表示worker已经用完，那么需要循环等待，
         * 直到得到
         */
        toWorkerConnFd = -1;
        
        //如果没有得到toWorkerFd,不让循环退出
        while(true)
        {
            pthread_mutex_lock(&toWorkerFdsLock);
            for(int i = 0;i < pArg->pMaster->toWorkerFds.size(); ++i)
            {
                if(pArg->pMaster->toWorkerFds[i] > 0)
                {
                    toWorkerConnFd = pArg->pMaster->toWorkerFds[i];
                    pArg->pMaster->toWorkerFds[i] = -1 * toWorkerConnFd;
                    toWorkerConnFdIndex = i;
                    break;
                }
            }
            pthread_mutex_unlock(&toWorkerFdsLock);
            if(toWorkerConnFd == -1)
            {
                usleep(10);
            }
            else
            {
                break;
            }
        }
        //得到toWorkerFd,向toWorkerConnFd发送数据
        while((n = pBuff->Get(buff,BUFF_SIZE)) > 0)
        {
             write(toWorkerConnFd,buff,n);
        }
        //从toWorkerFd中读取处理后的数据,不需要缓存，直接传给客户端
        read(toWorkerConnFd,(void*)&size,SIZEOF_UNSIGNED_INT);
        write(toMasterConnFd,(void*)&size,SIZEOF_UNSIGNED_INT);
        while(size > 0)
        {
            if(size > BUFF_SIZE)
            {
                needReadCount = BUFF_SIZE;
            }
            else
            {
                needReadCount = size;
            }
            n = read(toWorkerConnFd,buff,needReadCount);
            size -= n;
            write(toMasterConnFd,buff,n);
        }
        //当数据写完，就应该把toWorkerConnFd的状态置为可以处理
        pthread_mutex_lock(&toWorkerFdsLock);
        pArg->pMaster->toWorkerFds[toWorkerConnFdIndex] = -1 * toMasterConnFd;
        pthread_mutex_unlock(&toWorkerFdsLock);
        //一个处理周期结束.
    }
}

JAdapter::~JAdapter() {
}

